home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C++ / Applications / ResAnomaly 1.2 / ResAnomaly Source / FrDropApp.cp < prev    next >
Encoding:
Text File  |  1995-10-21  |  11.2 KB  |  452 lines  |  [TEXT/MMCC]

  1.  
  2. // * This is ResAnomaly.        Based on FrDropApp
  3. // * ©1995 Chris K. Thomas.        ©1994 Metrowerks Inc. All Rights Reserved.
  4.  
  5. /*
  6.     ckt July the Second 1995
  7.     
  8.     Grab text resources up front to support the current architecture of
  9.     ResAnomaly. Eventually, I think we're going to go to three stages:
  10.     
  11.         …resource file is open
  12.     Stage One:      Data retrieval.  Gather all the named resources
  13.                     in the file into a list.
  14.         …resource file is closed
  15.     
  16.     Stage Two:      Analysis.  Check to be sure
  17.                     there aren't duplicate names & other stuff
  18.     
  19.     Stage Three:    Emitter.  Write the data in the proper format
  20.                     to the output stream.
  21.     
  22.     Currently, we only effectively have a mixed version of stages 1 & 3,
  23.     and the resource file is open throughout, which makes it difficult
  24.     to get to our own resources without abusing the Resource Mangler.
  25.     
  26.     ckt August 23 1995
  27.     
  28.     Getting ready for System 8.
  29. */
  30.  
  31. #define DEBUG_ME Yes, Please
  32.  
  33. #if (defined DEBUG_ME) && (defined __powerc)
  34. #pragma traceback on
  35. #endif
  36.  
  37. // ————• Us
  38. #include "FrDropApp.h"
  39. #include "SpinCursorLib.h"
  40. //#include <ctype.h>  // why isn't isspace() inline???????????????
  41. #include "ckt/ctype.h"
  42.  
  43. // * rewriting ANSI C library to circumvent inclusion of
  44. // * the whole library is annoying!
  45.  
  46. #include "System8Resources.h"
  47.  
  48. // ————• PP
  49. #include <UException.h>
  50. #include <LModelDirector.h>
  51. #include <LFileStream.h>
  52. #include <UAppleEventsMgr.h>
  53. #include <LHandleStream.h>
  54. #include <UMemoryMgr.h>
  55.  
  56. // ————• my less annoying (to the programmer) standard file replacement
  57. #include "StFile.h"
  58.  
  59. const ResIDT    ALRT_NoFiles    = 200;
  60.  
  61. static void InsertTextIntoStream(Handle inOurResource, LStream &inStream);
  62. static void InsertTextIntoStream(short inID, LStream &inStream);
  63. static void AddDotExtension(Str255 ioString, const Str255 inDot);
  64.  
  65. // ===========================================================================
  66. //        • Main Program
  67. // ===========================================================================
  68.  
  69. void main(void)
  70. {
  71.     try
  72.     {
  73.         FrDropApp    gApp;
  74.         gApp.Run();
  75.     }
  76.     catch(...)
  77.     {
  78.         ParamText("\pResAnomaly: I don't understand why, but I can't finish the task.", "\p", "\p", "\p");
  79.         StopAlert(129, NULL);
  80.     }
  81. }
  82.  
  83.  
  84. // ===========================================================================
  85. //        • FrDropApp Class
  86. // ===========================================================================
  87.  
  88. FrDropApp::FrDropApp()
  89. {
  90.     MaxApplZone();
  91.  
  92.     InitGraf((Ptr) &qd.thePort);        // Toolbox Managers
  93.     InitFonts();
  94.     InitWindows();
  95.     InitMenus();
  96.     TEInit();
  97.     InitDialogs(nil);
  98.     
  99.     new LModelDirector(this);            // AppleEvent Handlers
  100.     
  101.     mRunning = true;
  102.     
  103.     // * preload our text, because we can't access
  104.     // * our res file during processing
  105. /*    
  106.     mTextBeginLine = Get1Resource('TEXT', 128);
  107.     mTextIDequals = Get1Resource('TEXT', 130);
  108.     mTextIDend = Get1Resource('TEXT', 131);
  109.     mOutputHeaderStart = Get1Resource('TEXT', 256);
  110.     mOutputHeaderStop = Get1Resource('TEXT', 257);
  111. */
  112.     RMGetResource('TEXT', 128, true, true, &mTextBeginLine);
  113.     RMGetResource('TEXT', 130, true, true, &mTextIDequals);
  114.     RMGetResource('TEXT', 131, true, true, &mTextIDend);
  115.     RMGetResource('TEXT', 256, true, true, &mOutputHeaderStart);
  116.     RMGetResource('TEXT', 257, true, true, &mOutputHeaderStop);
  117.     
  118.     ThrowIfNULL_(mTextBeginLine);
  119.     ThrowIfNULL_(mTextIDequals);
  120.     ThrowIfNULL_(mTextIDend);
  121.     ThrowIfNULL_(mOutputHeaderStart);
  122.     ThrowIfNULL_(mOutputHeaderStop);
  123.     
  124.     ReadPrefs();
  125. }
  126.  
  127.  
  128. void
  129. FrDropApp::ReadPrefs()
  130. {
  131.     FSSpec    ourSpec;
  132.     
  133.     FSMakeFSSpec(0, 0, "\pPrefs.rsrc", &ourSpec);
  134.     LFile    prefsFile(ourSpec);
  135.     prefsFile.OpenResourceFork(fsRdPerm);
  136.     
  137. //    ResAnomalyPrefs    **ourPrefs = (ResAnomalyPrefs **)GetResource('®prf', 128);
  138.     
  139.     ResAnomalyPrefs    **ourPrefs;
  140.     
  141.     RMGetResource('®prf', 128, true, true, (Handle *) &ourPrefs);
  142.     ThrowIfNULL_(ourPrefs);
  143.     
  144.     BlockMoveData(*ourPrefs, &mCurrentPrefs, sizeof(ResAnomalyPrefs));
  145.     
  146.     RMReleaseResource((Handle)ourPrefs);
  147.     prefsFile.CloseResourceFork();
  148. }
  149.  
  150.  
  151. void
  152. FrDropApp::Run()
  153. {
  154.         // This program has no user interface. We only care
  155.         // about AppleEvents.
  156.         
  157.     while (mRunning) {
  158.         EventRecord        macEvent;
  159.         if (WaitNextEvent(everyEvent, &macEvent, 2, nil)) {
  160.         
  161.             if (macEvent.what == kHighLevelEvent) {
  162.                 AEProcessAppleEvent(&macEvent);
  163.             }
  164.         }
  165.     }
  166. }
  167.  
  168.  
  169. void
  170. FrDropApp::HandleAppleEvent(
  171.     const AppleEvent    &inAppleEvent,
  172.     AppleEvent            &outAEReply,
  173.     AEDesc                &outResult,
  174.     long                inAENumber)
  175. {
  176.     switch (inAENumber) {
  177.     
  178.         case ae_OpenApp:
  179.             StartUp();
  180.             break;
  181.             
  182.         case ae_OpenDoc:
  183.             DoAEOpenDoc(inAppleEvent, outAEReply, inAENumber);
  184.             break;
  185.             
  186.         case ae_Quit:
  187.             DoQuit();
  188.             break;
  189.             
  190.         default:
  191.             LModelObject::HandleAppleEvent(inAppleEvent, outAEReply, outResult, inAENumber);
  192.             break;
  193.     }
  194. }
  195.  
  196.  
  197. void
  198. FrDropApp::StartUp()
  199. {
  200.         // User double-clicked on the Program's icon
  201.         
  202.         // This program only works when files are dragged on the
  203.         // program's icon in the Finder. So we just display an
  204.         // Alert (which could have instructions for using the program)
  205.         // and then quit.
  206.     
  207.     ::Alert(ALRT_NoFiles, nil);
  208.     DoQuit();
  209. }
  210.  
  211.  
  212. void
  213. FrDropApp::DoAEOpenDoc(
  214.     const AppleEvent    &inAppleEvent,
  215.     AppleEvent&            /*outAEReply*/,
  216.     long                /*inAENumber*/)
  217. {
  218.     AEDescList    docList;
  219.     OSErr        err = AEGetParamDesc(&inAppleEvent, keyDirectObject,
  220.                             typeWildCard, &docList);
  221.     if (err != noErr) Throw_(err);
  222.     
  223.     Int32    numDocs;
  224.     err = AECountItems(&docList, &numDocs);
  225.     if (err != noErr) Throw_(err);
  226.     
  227.         // Loop through all items in the list
  228.             // Extract descriptor for the document
  229.             // Coerce descriptor data into a FSSpec
  230.             // Tell Program object to open document
  231.         
  232.     for (Int32 i = 1; i <= numDocs; i++) {
  233.         AEKeyword    theKey;
  234.         DescType    theType;
  235.         FSSpec        theFileSpec;
  236.         Size        theSize;
  237.         err = AEGetNthPtr(&docList, i, typeFSS, &theKey, &theType,
  238.                             (Ptr) &theFileSpec, sizeof(FSSpec), &theSize);
  239.         if (err != noErr) Throw_(err);
  240.         OpenDocument(&theFileSpec);
  241.     }
  242.     
  243.     AEDisposeDesc(&docList);
  244.     
  245.     DoQuit();
  246. }
  247.  
  248.  
  249. void
  250. FrDropApp::OpenDocument(
  251.     FSSpec    *inMacFSSpec)
  252. {
  253.     FSSpec            saveSpec = *inMacFSSpec;
  254.     Handle            curRes;
  255.     UInt32            numTypes;
  256.     UInt32            numRes;
  257.     UInt32            i, j;
  258.     short            currentID;
  259.     ResType            currentType;
  260.     Str255            currentName;
  261.     Str255            numString;
  262.     LHandleStream    ourStream;
  263.     CursorSet        busyCursor(256, 4);
  264.     
  265.     InsertTextIntoStream(mOutputHeaderStart, ourStream);
  266.     ourStream.WriteData(&inMacFSSpec->name[1], inMacFSSpec->name[0]);
  267.     InsertTextIntoStream(mOutputHeaderStop, ourStream);
  268.     
  269.     Try_{
  270.         LFile            resFile(*inMacFSSpec);
  271.         ResType            validCtype;
  272.         OSStatus        ourStatus;
  273.         
  274.         SetResLoad(false);
  275.         resFile.OpenResourceFork(fsRdPerm);
  276.         SetResLoad(true);
  277.         
  278.         RMCountTypes(true, &numTypes);
  279.         
  280.         // * this loop gets each resource type
  281.         for(i = 1; i <= numTypes; i++)
  282.         {
  283.             
  284.             ourStatus = RMGetIndexedType(i, true, ¤tType);
  285.             ThrowIfOSErr_(ourStatus);
  286. //            Get1IndType(¤tType, i);
  287. //            ThrowIfResError_();
  288.             
  289.             // * map the type to valid C-language chars
  290.             // * for use in writing to output header
  291.             validCtype = currentType;
  292.             MapToValidC(4, &validCtype);
  293.             
  294.             ourStatus = RMCountResources(currentType, true, &numRes);
  295.             
  296. //            numRes = Count1Resources(currentType);
  297. //            ThrowIfResError_();
  298.             
  299.             // * this loop processes each individual resource in
  300.             // * the previously gotten type.
  301.             for(j = 1; j <= numRes; j++)
  302.             {
  303.                 busyCursor.Spin();
  304.                 
  305.                 RMGetIndexedResource(currentType, j, true, false, &curRes);
  306. //                SetResLoad(false);
  307. //                curRes = Get1IndResource(currentType, j);
  308. //                SetResLoad(true);
  309.                 
  310. //                ThrowIfResError_();
  311.                 ThrowIfNULL_(curRes);
  312.                 
  313.                 ourStatus = RMGetResInfo(curRes, NULL, ¤tID, currentName);
  314. //                GetResInfo(curRes, ¤tID, NULL, currentName);
  315.                 ThrowIfOSErr_(ourStatus);
  316.                 
  317.                 // * if the resource isn't named, how does one identify it?
  318.                 if(currentName[0] > 0)
  319.                 {
  320.                     MapToValidC(currentName);    //convert name to C-language usable
  321.                     
  322.                     // * Write a type string in the format const short kResNameType = 'type';
  323.                     
  324.     //                    InsertTextIntoStream(128, ourStream);    // "const kResource"
  325.     //                    ourStream.WriteData(¤tName[1], currentName[0]); // "<name>"
  326.     //                    InsertTextIntoStream(129, ourStream);    // "Type = '"
  327.     //                    ourStream.WriteData(¤tType, sizeof(ResType)); // "tnam"
  328.     //                    InsertTextIntoStream(131, ourStream);    // "';\r"
  329.                     
  330.                     // * Write an ID string in the format const short kResNameID = id#;
  331.                     InsertTextIntoStream(mTextBeginLine, ourStream);    // "const kResource"
  332.                     ourStream.WriteData(¤tName[1], currentName[0]); // "<name>"
  333.                     ourStream.WriteData(&validCtype, sizeof(ResType));    //tnam
  334.                     InsertTextIntoStream(mTextIDequals, ourStream);    // "ID = '"
  335.                     NumToString(currentID, numString);
  336.                     ourStream.WriteData(&numString[1], numString[0]);
  337.                     InsertTextIntoStream(mTextIDend, ourStream);    // "';\r"
  338.                 }
  339.                 
  340.                 RMReleaseResource(curRes);
  341.             }
  342.         }
  343.  
  344.         resFile.CloseResourceFork();
  345.         
  346.         // * we can now safely access our own resources
  347.         
  348.         AddDotExtension(inMacFSSpec->name, mCurrentPrefs.rapDotExtension);
  349.     
  350.         StPutFile    newFile("\pSave Resource Constants as:", *inMacFSSpec);
  351.         
  352.         if(newFile.reply.sfGood)
  353.         {
  354.             LFile        ourFile(newFile.reply.sfFile);
  355.             
  356.             if(newFile.reply.sfReplacing)
  357.                 ThrowIfOSErr_(FSpDelete(&newFile.reply.sfFile));
  358.             
  359.             ourFile.CreateNewDataFile(mCurrentPrefs.rapCreator, 'TEXT');
  360.             
  361.             StHandleLocker stlock(ourStream.GetDataHandle());
  362.             
  363.             ourFile.OpenDataFork(fsWrPerm);
  364.             ourFile.WriteDataFork(*ourStream.GetDataHandle(), ourStream.GetLength());
  365.             ourFile.CloseDataFork();
  366.         }
  367.     }
  368.     Catch_(inErr)
  369.     {
  370.         Str255 str;
  371.         
  372.         NumToString(inErr,str);
  373.         ParamText(inMacFSSpec->name, str, "\p", "\p");
  374.         CautionAlert(129, NULL);
  375.     } EndCatch_
  376. }
  377.  
  378. // * add a .dot extension to a Mac filename (yuk!)
  379. // * this would make a good alternate constructor argument for
  380. // * StPutFile.
  381. void AddDotExtension(Str255 ioString, const Str255 inDot)
  382. {
  383.     if(ioString[0] >= 32 - inDot[0]) //make space if necessary
  384.         ioString[0] -= inDot[0];
  385.     
  386.     BlockMoveData(&inDot[1], &ioString[ioString[0] + 1], inDot[0]);
  387.     ioString[0] +=inDot[0];
  388.     // * yeah, I know that can be optimized
  389. }
  390.  
  391. // * map a string to valid C chars only.
  392. void FrDropApp::MapToValidC(Str255 ioString)
  393. {
  394.     for(long i = 1; i <= ioString[0]; i++)
  395.     {
  396.         if(isspace(ioString[i]))    //whitespace
  397.         {
  398.             ioString[i] = mCurrentPrefs.rapReplaceWhitespace;
  399.         }
  400.         else if(!isalphanum(ioString[i])) //english characters or numbers
  401.         {
  402.             ioString[i] = mCurrentPrefs.rapReplaceNonAlphaNumeric;
  403.         }
  404.     }
  405. }
  406.  
  407. // * map any number of characters to valid C chars
  408. void FrDropApp::MapToValidC(long inLength, void *ioChars)
  409. {
  410.     unsigned char    *ioString = (unsigned char *)ioChars;
  411.     
  412.     for(long i = 1; i <= inLength; i++)
  413.     {
  414.         if(isspace(ioString[i]))    //whitespace
  415.         {
  416.             ioString[i] = mCurrentPrefs.rapReplaceWhitespace;
  417.         }
  418.         else if(!isalphanum(ioString[i])) //english characters or numbers
  419.         {
  420.             ioString[i] = mCurrentPrefs.rapReplaceNonAlphaNumeric;
  421.         }
  422.     }
  423. }
  424.  
  425.  
  426. void InsertTextIntoStream(Handle inOurResource, LStream &inStream)
  427. {
  428.     ThrowIfNULL_(inOurResource);
  429.     
  430.     StHandleLocker    stlock(inOurResource);
  431.     inStream.WriteData(*inOurResource, GetHandleSize(inOurResource));
  432. }
  433.  
  434.  
  435. // * insert contents of a 'TEXT' resource into an LStream
  436. void InsertTextIntoStream(short inID, LStream &inStream)
  437. {
  438.     Handle ourResource = Get1Resource('TEXT', inID);
  439.     
  440.     InsertTextIntoStream(ourResource, inStream);
  441.     
  442. //    purposely don't dispose text - res manager serves as cache mechanism
  443. //    not an efficient one, to be sure, but it works.
  444. // * * * can't use this safely when other res forks are open unless
  445. // * * * guarantee our home currency
  446. }
  447.  
  448. void
  449. FrDropApp::DoQuit()
  450. {
  451.     mRunning = false;
  452. }